#include "test.h"

extern int usr_interrupt;

void file_already_exists_test() {
	usr_interrupt = 0;

	char file_name[10] = "_test";

	int i = 0;
	for (; i < 100 && does_file_exist(file_name); i++) {
		snprintf(file_name, 10, "_test%d", i);
	}

	if (i == 100) {
		errx(EXIT_FAILURE, "Test file name creation timeout");
	}

	FILE *f = fopen(file_name, "w");
	if (f == NULL) {
		errx(EXIT_FAILURE, "Could not create test file.");
	}
	fclose(f);

	pid_t pid;
	switch (pid = fork()) {
		case -1:
			errx(EXIT_FAILURE, "Could not fork child process.");
			break;
		case 0: // I'm a child
			start_server("6071", NULL, 1);
			break;
		default: // I'm a father
			break;
	}

	struct addrinfo *res = NULL;
	struct addrinfo *resorig = NULL;

	int sock = get_socket(NULL, &res, &resorig, "6071");

	char *buff = malloc(PACKET_MAX_LENGTH);
	if (buff == NULL) {
		errx(EXIT_FAILURE, "Could not allocate memory.");
	}

	set_ushort(buff, WRQ);

	int indent = set_char_arr(buff, file_name, 2, 1);

	indent = set_char_arr(buff, "octet", indent, 1);

	int bytes_to_send = indent - 1;

	sigset_t mask, oldmask;
	// set up the mask of signals to temporarily block
	sigemptyset(&mask);
	sigaddset(&mask, SIGUSR1);

	// waiting for server to start
	sigprocmask(SIG_BLOCK, &mask, &oldmask);
	while (!usr_interrupt) {
		sigsuspend(&oldmask);
	}
	sigprocmask(SIG_UNBLOCK, &mask, NULL);

	sendto(sock, buff, bytes_to_send, 0, res->ai_addr, res->ai_addrlen);

	struct sockaddr_in faddr;
	socklen_t addrsize = sizeof (faddr);

	int n;
	if ((n = recvfrom(sock, buff, PACKET_MAX_LENGTH, 0, (struct sockaddr *)&faddr, &addrsize)) > 0) {
		short opcode = get_ushort(buff);
		short err_val = get_ushort(buff + 2);
		assert(opcode == ERROR);
		assert(err_val == FILE_EXISTS);
		printf("File already exists test: success\n");
	}

	kill(pid, SIGKILL);
	unlink(file_name);
}

void file_not_found_test() {
	usr_interrupt = 0;

	char file_name[10] = "_test";

	int i = 0;
	for (; i < 100 && does_file_exist(file_name); i++) {
		snprintf(file_name, 10, "_test%d", i);
	}

	if (i == 100) {
		errx(EXIT_FAILURE, "Test file timeout");
	}

	pid_t pid;
	switch (pid = fork()) {
		case -1:
			errx(EXIT_FAILURE, "Could not fork child process.");
			break;
		case 0: // I'm a child
			start_server("6071", NULL, 1);
			break;
		default: // I'm a father
			break;
	}

	struct addrinfo *res = NULL;
	struct addrinfo *resorig = NULL;

	int sock = get_socket(NULL, &res, &resorig, "6071");

	char *buff = malloc(PACKET_MAX_LENGTH);
	if (buff == NULL) {
		errx(EXIT_FAILURE, "Could not allocate memory.");
	}

	set_ushort(buff, RRQ);

	int indent = set_char_arr(buff, file_name, 2, 1);

	indent = set_char_arr(buff, "octet", indent, 1);

	int bytes_to_send = indent - 1;

	sigset_t mask, oldmask;

	// set up the mask of signals to temporarily block
	sigemptyset(&mask);
	sigaddset(&mask, SIGUSR1);

	// waiting for server to start
	sigprocmask(SIG_BLOCK, &mask, &oldmask);
	while (!usr_interrupt) {
		sigsuspend(&oldmask);
	}
	sigprocmask(SIG_UNBLOCK, &mask, NULL);

	sendto(sock, buff, bytes_to_send, 0, res->ai_addr, res->ai_addrlen);

	struct sockaddr_in faddr;
	socklen_t addrsize = sizeof (faddr);

	int n;
	if ((n = recvfrom(sock, buff, PACKET_MAX_LENGTH, 0, (struct sockaddr *)&faddr, &addrsize)) > 0) {
		short opcode = get_ushort(buff);
		short err_val = get_ushort(buff + 2);
		assert(opcode == ERROR);
		assert(err_val == FILE_NOT_FOUND);
		printf("File not found test: success\n");
	}

	kill(pid, SIGKILL);
}

void correct_sent_test() {
	usr_interrupt = 0;

	char file_name[10] = "_test";

	int i = 0;
	for (; i < 100 && does_file_exist(file_name); i++) {
		snprintf(file_name, 10, "_test%d", i);
	}

	if (i == 100) {
		errx(EXIT_FAILURE, "Test file name creation timeout");
	}

	pid_t pid;
	switch (pid = fork()) {
		case -1:
			errx(EXIT_FAILURE, "Could not fork child process.");
			break;
		case 0: // I'm a child
			start_server("6071", NULL, 1);
			break;
		default: // I'm a father
			break;
	}
	struct addrinfo *res = NULL;
	struct addrinfo *resorig = NULL;

	int sock = get_socket(NULL, &res, &resorig, "6071");

	sigset_t mask, oldmask;

	// set up the mask of signals to temporarily block
	sigemptyset(&mask);
	sigaddset(&mask, SIGUSR1);

	// waiting for server to start
	sigprocmask(SIG_BLOCK, &mask, &oldmask);
	while (!usr_interrupt) {
		sigsuspend(&oldmask);
	}
	sigprocmask(SIG_UNBLOCK, &mask, NULL);

	int ret_val = send_file(sock, file_name, res, "test/large.jpg", OCTET);

	if (ret_val == EXIT_FAILURE) {
		fprintf(stderr, "Correct sent test: fail\n");
		return;
	}

	free(resorig);
	close(sock);

	kill(pid, SIGKILL);

	if (!compare(file_name, "test/large.jpg")) {
		fprintf(stderr, "Correct sent test: fail\n");
		unlink(file_name);
		exit(EXIT_FAILURE);
	} else {
		fprintf(stderr, "Correct sent test: success\n");
		unlink(file_name);
	}

}